package com.zhang.handler;

import com.zhang.ClientChannelManage;
import com.zhang.HttpChannelManage;
import com.zhang.common.Constant;
import com.zhang.common.codec.MyHttpObjectAggregator;
import com.zhang.common.codec.MyHttpRequestEncoder;
import com.zhang.common.message.ProxyMessageUtil;
import com.zhang.event.TransferFail;
import com.zhang.event.TransferSuccess;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * 处理所有的http请求类
 * @author 98265
 */
public class HttpServerHandler extends ChannelInboundHandlerAdapter {

    /**
     * 日志对象
     */
    static private Logger log = LoggerFactory.getLogger(HttpServerHandler.class);
    /**
     * http request 编码器
     */
    private MyHttpRequestEncoder encoder = new MyHttpRequestEncoder();

    private MyHttpObjectAggregator aggregator = new MyHttpObjectAggregator(2*1024*1024);

    /**
     * 默认是不能转发出去的   需要先建立好连接
     */
    private volatile boolean transfer = false;

    /**
     * 存储 代理服务器未连接真实服务器 这段时间的数据
     */
    private List<FullHttpRequest> message = new ArrayList<>();

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        log.debug("HttpServerHandler处理request消息类型数据");
        if (msg instanceof  FullHttpRequest){
            FullHttpRequest request = (FullHttpRequest) msg;

            synchronized (this){
                if(!transfer){
                    message.add(request);
                    return;
                }
            }

            handle(ctx,request);
        }else {
            ReferenceCountUtil.release(msg);
            log.error("丢弃消息");
        }

    }

    private void handle(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
        //获取浏览器请求的域名
        String domain = ctx.channel().attr(Constant.DOMAIN).get() + "";
        Channel channel = ClientChannelManage.getChannelByDomain(domain);
        if(channel == null ){
            log.error("代理客户端不在线");
            ctx.close();
            return;
        }
        //存储httpchannel
        Long httpId = HttpChannelManage.getHttpIdByChannel(ctx.channel());

        List<Object> list = new ArrayList<>();
        encoder.encode(ctx,request,list);

        for(Object o:list){
            ByteBuf buf = (ByteBuf) o;
            byte[] data = ByteBufUtil.getBytes(buf);
            buf.release();
            //发送带有http数据 自定义消息
            channel.writeAndFlush(ProxyMessageUtil.buildTransferReq(httpId,data));
            log.debug("发送用户http数据给真实服务器 {}",httpId);
        }
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if(evt instanceof TransferSuccess){
            log.debug("启动消息转发");
            synchronized (this){
                this.transfer = true;
            }
            //开始转发请求
            for (FullHttpRequest request:message){
                handle(ctx,request);
            }
            message.clear();
            return;
        }
        if(evt instanceof TransferFail){
            message.clear();
        }
        super.userEventTriggered(ctx, evt);
    }
}
